// 泛型的使用方法
function identity<T>(arg: T): T {
    return arg;
}

// 使用方法一 提前写好类型
let output = identity<string>("myString");

// 使用方法二 类型推论
let output1 = identity("myString");


// 使用泛型变量
// function getLength<T>(arg: T): T {
//     // console.log(arg.length); //error
//     return arg
// }

function getLength<T>(arg: Array<T>): Array<T> {
    console.log(arg.length);
    return arg
}



// 泛型接口
interface Identities<V, W> {
    id1: V,
    id2: W
}

function identities<T, U>(arg1: T, arg2: U): Identities<T, U> {
    console.log(arg1 + ": " + typeof (arg1));
    console.log(arg2 + ": " + typeof (arg2));
    let identities: Identities<T, U> = {
        id1: arg1,
        id2: arg2
    };
    return identities;
}



// 泛型类
class GenericNumber<T> {
    value: T;
    add: (x: T, y: T) => T
}
let myGenericNumber = new GenericNumber<number>()
myGenericNumber.value = 1
myGenericNumber.add = function (x, y) {
    return x + y
}
// console.log(myGenericNumber.add(myGenericNumber.value, 2));



// 泛型约束
interface Lengthwise {
    length: number;
}
function loggingIdentity<T extends Lengthwise>(arg: T): T {
    console.log(arg.length);
    return arg
}
// 我们需要传入符合约束类型的值，必须包含必须的属性：
console.log(loggingIdentity({ length: 1, value: 'zs' }));



// 在泛型约束中使用类型参数
// 你可以声明一个类型参数，且它被另一个类型参数所约束。比如，
function find<T, U extends T>(n: T, s: U) {
    // ...
}
// find(giraffe, myAnimals);




